package sk.fiit.lulco.grafy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * class for generation
 */
public class Generation {
	
	private int number;
	
	private List<Graph> individuals = new ArrayList<Graph>();
	
	private boolean sorted = false;
	
	private GenerationStats generationStats = null;
	
	private static final GraphFitnessComparator graphFithessComparator = new GraphFitnessComparator(
			HEALConstants.SortType.DESC);
	
	public void setNumber(int number) {
		this.number = number;
	}
	
	public void setIndividuals(List<Graph> individuals) {
		this.individuals = individuals;
	}
	
	public void addIndividual(Graph individual) {
		this.individuals.add(individual);
	}
	
	public void addIndividuals(List<Graph> individuals) {
		this.individuals.addAll(individuals);
	}
	
	public boolean removeIndividual(Graph individual) {
		return this.individuals.remove(individual);
	}
	
	public List<Graph> getIndividuals() {
		return this.individuals;
	}
	
	public void sortIndividualsByFitness() {
		Collections.sort(this.getIndividuals(), graphFithessComparator);
		this.setSorted(true);
	}
	
	public Graph getBestIndividual() {
		if (this.sorted == false) {
			this.sortIndividualsByFitness();
		}
		return this.getIndividuals().get(0);
	}
	
	public void setSorted(boolean sorted) {
		this.sorted = sorted;
	}
	
	public boolean getSorted() {
		return this.sorted;
	}
	
	public void clearCache() {
		this.setSorted(false);
		this.setGenerationStats(null);
		for (Graph graph : this.getIndividuals()) {
			graph.clearFitness();
		}
	}
	
	public GenerationStats getGenerationStats() {
		if (this.generationStats == null) {
			int verticesCount = this.getIndividuals().size();
			double fitnessSum = 0;
			int conflictedEdgesSum = 0;
			int conflictedVerticesSum = 0;
			int timeToLiveSum = 0;
			List<Edge> conflictedEdges = new ArrayList<Edge>();
			for (Graph graph : this.getIndividuals()) {
				fitnessSum += graph.getFitness();
				conflictedEdges = graph.getConflitedEdges();
				conflictedEdgesSum += conflictedEdges.size();
				conflictedVerticesSum += graph.getConflictedVertices(conflictedEdges).size();
				timeToLiveSum += graph.getTimeToLive();
			}
			this.generationStats = new GenerationStats();
			this.generationStats.setGenerationNumber(this.number);
			this.generationStats.setBestIndividual(this.getBestIndividual());
			this.generationStats.setAverageFitness(fitnessSum / (double)verticesCount);
			this.generationStats.setAverageConflictedEdges((double)conflictedEdgesSum / (double)verticesCount);
			this.generationStats.setAverageConflictedVertices((double)conflictedVerticesSum / (double)verticesCount);
			this.generationStats.setAverageTimeToLive((double)timeToLiveSum / (double)verticesCount);
		}
		return this.generationStats;
	}
	
	public void setGenerationStats(GenerationStats generationStats) {
		this.generationStats = generationStats;
	}


}